package cate.game.activity.rebate;

import cate.common.table.activity.rebate.row.RebateBaseRow;
import cate.common.table.activity.rebate.row.RebateRow;
import cate.common.table.d.GDOperation;
import cate.game.activity.base.core.RoleActivitySingle;
import cate.game.activity.rebate.msg.RebateActivityInfoResp;
import cate.game.activity.rebate.po.RebateItem;
import cate.game.mail.po.MailBuilder;
import cate.game.res.MixRes;
import cate.game.role.Role;
import easy.java.dev.note.NoteField;

import java.util.*;


public class RebateActivity extends RoleActivitySingle {
    @NoteField("当日充值金额")
    public long todayPay;
    @NoteField("key为基础配置id，value为当前进行中的分组")
    public Map<Integer, Integer> groupIdMap;
    @NoteField("key为基础配置id，value为当前进行中的任务id")
    public Map<Integer, Integer> rewardIdMap;
    @NoteField(value = "当前分组中的所有返利任务", detail = "key为分组id")
    public Map<Integer, List<RebateItem>> rebateListMap;


    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (rebateListMap == null) {
            rebateListMap = new HashMap<>();
        }
        if (!rebateListMap.isEmpty()) {
            rebateListMap.values().forEach(rebateList -> rebateList.forEach(rebateItem -> rebateItem.initialize(role)));
        }
        if (groupIdMap == null) {
            groupIdMap = new HashMap<>();
        }
        if (rewardIdMap == null) {
            rewardIdMap = new HashMap<>();
        }
        role.getActivity().registerRecharge(this, this::tryRefreshReward);
    }

    //充值时尝试刷新奖励
    public void tryRefreshReward(long paid) {
        todayPay += paid;
        for (Integer id :
                rewardIdMap.values()) {
            RebateItem rebateItem = rebateListMap.values().stream().flatMap(Collection::stream).filter(item -> item.id == id).findAny().orElse(null);
            if (rebateItem != null && rebateItem.getBaseRow() != null
                    && todayPay >= rebateItem.getBaseRow().amount
                    && !rebateItem.available && !rebateItem.got) {
                rebateItem.available = true;
            }
        }
        noticeUpdate();
    }

    //玩家领取奖励
    public void getReward(int id) {
        RebateItem rebateItem = rebateListMap.values().stream().flatMap(Collection::stream).filter(item -> item.id == id).findAny().orElse(null);
        if (rebateItem == null) {
            role.getGame().notice.message(role, "未找到此配置");
            return;
        }
        if (!rebateItem.available) {
            role.getGame().notice.message(role, "不可领取此奖励");
            return;
        }
        if (rebateItem.got) {
            role.getGame().notice.message(role, "奖励已领取");
            return;
        }
        MixRes res = new MixRes(rebateItem.getRow().reward);
        res.add(role, true, GDOperation.REBATE_REWARD);
        role.getGame().notice.dialogReward(role, res);
        rebateItem.available = false;
        rebateItem.got = true;
        noticeUpdate();
    }


    //跨天
    @Override
    public void onDaySpan(boolean silence) {
        super.onDaySpan(silence);
        sendUnclaimedReward();
        updateToNext();
        todayPay = 0;
        noticeUpdate();
    }

    @Override
    public void onRoleOpen() {
        List<RebateBaseRow> rebateRows = getRebateBaseList(role.getGame().status.getOpenDay());
        rebateRows.forEach(row -> refreshRebateGroup(0, row.group));
    }

    @Override
    public void onRoleEnd() {
        sendUnclaimedReward();
        clear();
    }


    private void clear() {
        todayPay = 0;
        groupIdMap.clear();
        rewardIdMap.clear();
        rebateListMap.clear();
    }

    @Override
    public void initSend() {
        noticeUpdate();
    }

    private void updateToNext() {
        for (Integer key : new ArrayList<>(rewardIdMap.keySet())) {
            RebateItem rebateItem = rebateListMap.values().stream().flatMap(Collection::stream).filter(item -> item.id == rewardIdMap.get(key)).findAny().orElse(null);
            if (rebateItem == null) {
                continue;
            }
            RebateBaseRow base = rebateItem.getBaseRow();
            if (base == null) {
                continue;
            }
            if (todayPay < base.amount) {
                continue;
            }


            RebateItem next = rebateListMap.get(rebateItem.groupId).stream().filter(item -> item.day == rebateItem.day + 1).findAny().orElse(null);
            if (next != null) {
                this.rewardIdMap.put(key, next.id);
            } else {
                RebateBaseRow baseRow = getRebateBaseRow(role.getGame().status.getOpenDay(), rebateItem.getBaseRow().amount);
                if (baseRow != null) {
                    refreshRebateGroup(rebateItem.groupId, baseRow.group);
                }
            }
        }

    }

    public void sendUnclaimedReward() {
        for (Integer id : rewardIdMap.values()) {
            RebateItem rebateItem = rebateListMap.values().stream().flatMap(Collection::stream).filter(item -> item.id == id).findAny().orElse(null);
            if (rebateItem == null || !rebateItem.available || rebateItem.got || rebateItem.getBaseRow() == null || todayPay < rebateItem.getBaseRow().amount) {
                continue;
            }
            MixRes res = new MixRes(rebateItem.getRow().reward);
            if (res.isEmpty()) {
                continue;
            }
            sendMail(res, rebateItem.getBaseRow().mailId);
            rebateItem.available = false;
            rebateItem.got = true;
        }
    }

    private void sendMail(MixRes reward, int mailID) {
        MailBuilder mailBuilder = new MailBuilder();
        mailBuilder.setContentId(mailID).setReward(reward.copy())
                .setOperation(GDOperation.REBATE_REWARD);
        role.getMail().add(mailBuilder.build());
    }

    private List<RebateRow> getRebateList(int groupId) {
        return role.getGame().table.rebate.rebateSheet.groupMap.get(groupId);
    }

    private List<RebateBaseRow> getRebateBaseList(int day) {
        return role.getGame().table.rebate.rebateBase.getRowsByDay(day);
    }

    private RebateBaseRow getRebateBaseRow(int day, long money) {
        return role.getGame().table.rebate.rebateBase.getRowByDayAndMoney(day, money);
    }

    private void refreshRebateGroup(int oldId, int newId) {
        if (oldId > 0) {
            this.rebateListMap.remove(oldId);
            this.rewardIdMap.remove(oldId);
            this.groupIdMap.remove(oldId);
        }
        List<RebateRow> rows = getRebateList(newId);
        if (rows == null || rows.isEmpty()) {
            rows = getRebateList(oldId);
        }
        List<RebateItem> items = new ArrayList<>();
        for (RebateRow row : rows) {
            RebateItem item = new RebateItem(row);
            item.initialize(role);
            items.add(item);
        }
        if (getRebateList(newId) == null || getRebateList(newId).isEmpty()) {
            rebateListMap.put(oldId, items);
            this.rewardIdMap.put(oldId, rows.get(0).id);
            this.groupIdMap.put(oldId, newId);
        } else {
            rebateListMap.put(newId, items);
            this.rewardIdMap.put(newId, rows.get(0).id);
            this.groupIdMap.put(newId, newId);
        }
    }

    public void noticeUpdate() {
        role.sendNow(new RebateActivityInfoResp(this));
    }

    @Override
    public void excelCheck() {
    }
}
